# -*- coding: utf-8 -*-
from __future__ import print_function, division
#系统库
import time
import random
import types
#第三方库
#自定义库
import Serverlib
import Serverlib.game
import Serverlib.Mods


#日志
logger = Serverlib.logging.getLogger('SERVER')


#常量
#CM_HEAD = 1  # 卡牌移动位置从列表头开始
#CM_TAIL = 2  # 卡牌移动位置从列表尾开始
#CM_RAND = 3  # 卡牌移动位置为列表随机位置
#CM_SPEC = 4  # 指定卡牌对象


PH_START = 0
PH_CHECK = 1
PH_DRAW = 2
PH_ACTION = 3
PH_DISCARD = 4
PH_END = 5
PHASE_NAMES = [u'回合开始', u'判定', u'摸牌', u'出牌', u'弃牌', u'回合结束']


#字符串
BS_ER_errorsuitnum = u'错误的花色或者点数'
BS_ER_errorshuffle = u'错误的洗牌方式'

BS_HT_hpup = u'玩家{0}恢复了{1}点体力'
BS_HT_hpdown = u'玩家{0}流失了{1}点体力'
BS_HT_hpdamage = u'玩家{0}受到了来自{1}的{2}点伤害'
BS_HT_drawcard = u'玩家{0}从牌堆摸了{1}张牌'
BS_HT_discard = u'玩家{0}从手牌弃除了{1}'

BS_RN_pilelong = u'牌堆数量'
BS_RN_discardlong = u'弃牌堆的牌'
BS_RN_currentp = u'当前玩家'
BS_RN_handcard = u'玩家手牌'
BS_RN_currenthp = u'当前血量'
BS_RN_maxhp = u'最大血量'
BS_RN_general = u'所用武将'
BS_RN_delay = u'延时锦囊'
BS_RN_attackhorse = u'进攻马'
BS_RN_defendhorse = u'防御马'
BS_RN_weapon = u'武器'
BS_RN_armor = u'防具'


#基础包的状态变化函数
class FSM_Functions(object):
    @staticmethod
    def format_gamedata(fsm, params):
        """获取游戏数据
        u_id: 获取数据的玩家u_id
        """
        retdata = {}
        retdata[BS_RN_pilelong] = len(fsm.pile)
        retdata[BS_RN_discardlong] = len(fsm.discard)
        #retdata[BS_RN_currentp] = fsm.current_player.username
        retdata['players'] = []
        for player in fsm.playerlist:
            data = {}
            data[BS_RN_currenthp] = player.current_hp
            data[BS_RN_maxhp] = player.max_hp
            #进攻马
            if player.attackhorse:
                data[BS_RN_attackhorse] = dict(
                    name=player.attackhorse.name,
                    id=player.attackhorse.id
                    )
            else:
                data[BS_RN_attackhorse] = None
            #防守马
            if player.attackhorse:
                data[BS_RN_defendhorse] = dict(
                    name=player.defendhorse.name,
                    id=player.defendhorse.id
                    )
            else:
                data[BS_RN_defendhorse] = None
            #武器
            if player.weapon:
                data[BS_RN_weapon] = dict(
                    name=player.weapn.name,
                    id=player.weapn.id
                    )
            else:
                data[BS_RN_weapon] = None
            #防具
            if player.armor:
                data[BS_RN_armor] = dict(
                    name=player.armor.name,
                    id=player.armor.id
                    )
            else:
                data[BS_RN_armor] = None
            #武将
            #延时类锦囊
            data[BS_RN_delay] = []
            for card in player.delay_strategy:
                delay = dict(
                    name=card.name,
                    id=card.id
                    )
                data[BS_RN_delay].append(delay)
            #手牌
            for card in player.handcard:
                hand = dict(
                    name=card.name,
                    id=card.id
                    )
                data[BS_RN_handcard].append(hand)
            retdata['players'].append(data)
        return retdata


class EventsHandlers(object):
    #洗牌函数
    @staticmethod
    def _shc_0(fsm, shufflelist):
        """默认模式"""
        random.seed(time.time())
        random.shuffle(shufflelist)
        return

    @staticmethod
    def _shc_1(fsm, shufflelist):
        """随机摸选"""
        return

    @staticmethod
    def _shc_2(fsm, shufflelist):
        """切牌"""
        return

    @staticmethod
    def _shc_3(fsm, shufflelist):
        """交叉洗牌"""
        return

    @staticmethod
    def _shc_4(fsm, shufflelist):
        """竖切"""
        return

    @staticmethod
    def _shc_5(fsm, shufflelist):
        """美式洗牌"""
        return

    @staticmethod
    def game_start(fsm, params):
        """游戏开始
        """
        hintstring = ""
        #往牌堆里添加所有卡牌
        cid = 0
        for cardclass in cardset:
            cardlist = cardset[cardclass]
            for suitnum in cardlist:
                card = None
                exec("card = {0}(suitnum)".format(cardclass))
                card.id = cid
                fsm.pile.append(card)
                fsm.cardmap[cid] = card
                cid += 1
        #洗牌
        params = dict(
            usage=0,
            shufflelist=fsm.pile
            )
        fsm.on_event('shuffle_cards', params)
        #座位
        fsm.playerlist = fsm.players.values()
        random.shuffle(fsm.playerlist)
        sid = 0
        for player in fsm.playerlist:
            fsm.players[player.u_id].seat_id = sid
            sid += 1
        #分发身份
        return 0, hintstring

    @staticmethod
    def shuffle_cards(fsm, params):
        """洗牌
        usage: 洗牌方式
        0：默认模式
        1: 随机摸选
        2: 切牌
        3: 交叉洗牌
        4: 分堆法
        5: 竖切
        6: 美式洗牌
        shufflelist: 洗牌堆
        """
        usage = params['usage']
        shufflelist = params['shufflelist']
        funcname = "_shc_" + str(usage)
        func = getattr(EventsHandlers, funcname)
        func(fsm, shufflelist)
        return 0, ""

    @staticmethod
    def phase_change(fsm, params):
        """阶段变化
        phase_now: 当前阶段
        phase_to: 下一个阶段,为空时默认
        """
        hintstring = ""
        return 0, hintstring

    @staticmethod
    def play_card(fsm, params):
        """打出手牌
        player: 打出手牌的人
        card: 打出的手牌
        """
        player = params['player']
        card = params['card']
        #把牌从手牌移动到弃牌堆
        player.handcard.remove(card)
        fsm.discard.append(card)
        #发挥牌的效果
        return card.on_play(fsm)

    @staticmethod
    def draw_card(fsm, params):
        """摸牌
        player: 摸牌的玩家对象
        num: 摸牌的数量
        """
        player = params['player']
        num = params['num']
        #把牌从牌堆移动到手牌
        cardlist = fsm.pile[0:num]
        fsm.pile = fsm.pile[num:]
        player.handcard.extend(cardlist)
        return 0, [BS_HT_drawcard.format(player.username, num)]

    @staticmethod
    def discard_card(fsm, params):
        """弃牌
        player: 弃牌的玩家对象
        cardlist: 弃除的牌的对象
        """
        player = params['player']
        cardlist = params['cardlist']
        #把牌从手牌移动到弃牌堆
        hintlist = []
        for card in cardlist:
            player.handcard.remove(card)
            fsm.discard.append(card)
            hintlist.append(BS_HT_discard.format(player.username, card))
        return 0, hintlist

    @staticmethod
    def hp_up(fsm, params):
        """回血
        player: 回血的玩家对象
        num: 回血的数量
        """
        player = params['player']
        num = params['num']
        player.current_hp += num
        ret = player.current_hp - player.max_hp
        if ret > 0:
            player.current_hp = player.max_hp
        return ret, [BS_HT_hpup.format(player.username, num)]

    @staticmethod
    def hp_down(fsm, params):
        """体力流失
        player: 体力流失的玩家对象
        num: 流失的体力数量
        """
        player = params['player']
        num = params['num']
        player.current_hp -= num
        return 0, BS_HT_hpdown.format(player.username, num)

    @staticmethod
    def hp_damage(fsm, params):
        """受到伤害
        from: 制造伤害的玩家
        to: 受到伤害的玩家
        num: 受到的伤害数
        """
        from_ = params['from']
        to = params['to']
        num = params['num']
        to.current_hp -= num
        return 0, [BS_HT_hpdamage.format(to.username, from_.username, num)]

    @staticmethod
    def equip_card(player, card):
        """装备手牌
        player: 打出装备的人
        card: 打出的装备
        """
        pass

    @staticmethod
    def check_card(player):
        """判定
        player: 判定的玩家
        """
        pass


#基础包卡牌
class Card(object):
    ST_UNKNOWN = 0
    ST_SPADE = 1
    ST_HEART = 2
    ST_DIAMOND = 3
    ST_CLUB = 4
    ST_NAME = ['无花色', '黑桃', '红心', '梅花']

    NUM_NAME = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']

    CL_NONE = 0
    CL_RED = 1
    CL_BLACK = 2

    def __init__(self, string=None):
        self.suitstring = string
        self.suit = Card.ST_UNKNOWN
        self.color = Card.CL_NONE
        self.num = 0
        self.name = None
        self.id = 0
        if string == None:
            return
        if len(string) != 2 and len(string) != 3:
            raise Exception(BS_ER_errorsuitnum)
        suit = string[0]
        if suit == 'S':
            self.suit = Card.ST_SPADE
            self.color = Card.CL_BLACK
        elif suit == 'H':
            self.suit = Card.ST_HEART
            self.color = Card.CL_RED
        elif suit == 'D':
            self.suit = Card.ST_DIAMOND
            self.color = Card.CL_RED
        elif suit == 'C':
            self.suit = Card.ST_CLUB
            self.color = Card.CL_BLACK
        try:
            num = int(string[1:])
            if num < 1 or num > 13:
                raise Exception(BS_ER_errorsuitnum)
            self.num = num
        except Exception:
            raise Exception(BS_ER_errorsuitnum)

    def __str__(self):
        string = "{0}{1}-{2}".format(Card.ST_NAME[self.suit], Card.NUM_NAME[self.num], self.name)
        return string

    def check_color(self, color):
        if self.color == color:
            return True
        return False

    def check_suit(self, suit):
        if self.suit == suit:
            return True
        return False

    def on_play(self, fsm):
        pass


class NormalCard(Card):
    def __init__(self, string=None):
        super(NormalCard, self).__init__(string)
        return None


class EquipCard(Card):
    def __init__(self, string=None):
        super(EquipCard, self).__init__(string)
        return None


class Armor(EquipCard):
    def __init__(self, string=None):
        super(Armor, self).__init__(string)
        return None


class Weapon(EquipCard):
    def __init__(self, string=None):
        super(Weapon, self).__init__(string)
        return None


class Weapon(EquipCard):
    def __init__(self, string=None):
        super(Weapon, self).__init__(string)
        return None


class Attackhorse(EquipCard):
    def __init__(self, string=None):
        super(Attackhorse, self).__init__(string)
        return None


class Defendhorse(EquipCard):
    def __init__(self, string=None):
        super(Defendhorse, self).__init__(string)
        return None


class StrategyCard(Card):
    def __init__(self, string=None):
        super(StrategyCard, self).__init__(string)
        return None


class Delaystrategy(StrategyCard):
    def __init__(self, string=None):
        super(Delaystrategy, self).__init__(string)
        return None


class Normalstrategy(StrategyCard):
    def __init__(self, string=None):
        super(Normalstrategy, self).__init__(string)
        return None


class Kill(NormalCard):
    def __init__(self, string=None):
        super(Kill, self).__init__(string)
        return None


class Dodge(NormalCard):
    def __init__(self, string=None):
        super(Dodge, self).__init__(string)
        return None


class Peach(NormalCard):
    def __init__(self, string=None):
        super(Peach, self).__init__(string)
        return None


#基础包配置
fsm_props = [
    ['pile', types.ListType],  # 牌堆
    ['cardmap', types.DictType],  # 牌表
    ['discard', types.ListType],  # 弃牌堆
    ['current_player', types.NoneType],  # 当前玩家
    ['playerlist', types.ListType]  # 玩家列表
]

player_props = [
    ['general', types.ListType],
    ['handcard', types.ListType],
    ['delay_strategy', types.ListType],
    ['attackhorse', types.NoneType],
    ['defendhorse', types.NoneType],
    ['weapon', types.NoneType],
    ['armor', types.NoneType],
    ['seat_id', types.IntType],
    ['current_hp', types.IntType],
    ['max_hp', types.IntType],
    ['marks', types.ListType],
    ['current_state', types.IntType]
]

cardset = dict(
    Kill=[
    'D6', 'D7', 'D8', 'D9', 'D10', 'D13',
    'S7', 'S8', 'S8', 'S9', 'S9', 'S10', 'S10',
    'H10', 'H10', 'H11',
    'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C8', 'C9', 'C9', 'C10', 'C10', 'C11', 'C11'
    ],
    Dodge=[
    'D2', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8', 'D9', 'D10', 'D11', 'D11',
    'H2', 'H2', 'H13',
    ],
    Peach=[
    'D12',
    'H3', 'H4', 'H6', 'H7', 'H8', 'H9', 'H12'
    ]
)


#装载时
def on_load():
    Serverlib.Mods.load_fsm_prop(fsm_props)  # 装载规则中包含的场地属性
    Serverlib.Mods.load_player_prop(player_props)  # 装载规则中包含的玩家属性
    Serverlib.Mods.load_event_handlers(EventsHandlers, 'base')  # 装载规则中的事件处理函数
    Serverlib.Mods.load_fsm_funcs(FSM_Functions, 'base')  # 装载规则中的函数
